/* .抽象工厂模式（abstract factory）提供一个创建一系列相关或相互依赖的对象的接口。
本例对预处理进行模块化，分割算法进行模块化，然后将二者进行整合封装到一个类中. */

#include <iostream>
#include <memory>

using namespace std;

#pragma region //预处理模块

class Preprocessing
{
public:
    virtual void print_info() = 0;
};

// 截断归一化
class ClipNormalization :public Preprocessing
{
public:
    void print_info();
};
void ClipNormalization::print_info()
{
    cout<<"Using clip normalization to preprocessing."<<endl;
}

// 自适应归一化
class AdaptionNormalization:public Preprocessing
{
    public:
    void print_info();
};
void AdaptionNormalization::print_info()
{
    cout<<"Using adption normalization to preprocessing."<<endl;
}
#pragma endregion


#pragma region //分割模块

class Segment
{
public:
    virtual void print_result() = 0;
};

// 阈值分割
class SegmentThreshold:public Segment
{
public:
    void print_result();
};

void SegmentThreshold::print_result()
{
    cout<< "Using threshold to generate mask"<<endl;
}

// 区域生长
class SegmentGrowing :public Segment
{
public:
    void print_result();
};
void SegmentGrowing::print_result()
{
    cout<< "Using growing to generate mask"<<endl;
}

#pragma endregion



#pragma region // 抽象工厂
class AbstractFactory
{
public:
    virtual Preprocessing* set_preprocessing() = 0;
    virtual Segment* set_segment()=0;
};

// 具体工厂
class MRFactory: public AbstractFactory
{
public:
    Preprocessing* set_preprocessing();
    Segment* set_segment();
};
Preprocessing* MRFactory::set_preprocessing()
{
    return new AdaptionNormalization();
}
Segment* MRFactory::set_segment()
{
    return new SegmentGrowing();
}

// 具体工厂
class CTFactory:public AbstractFactory
{
public:
    Preprocessing* set_preprocessing();
    Segment* set_segment();
};
Segment* CTFactory::set_segment()
{
    return new SegmentThreshold();
}
Preprocessing* CTFactory::set_preprocessing()
{
    return new ClipNormalization();
}

#pragma endregion


void print_info(Preprocessing* pre, Segment* seg)
{
    pre->print_info();
    seg->print_result();
}

int main(int argc, char const *argv[])
{
    unique_ptr<AbstractFactory> factory_ptr =nullptr;
    unique_ptr<Preprocessing> pre_ptr = nullptr;
    unique_ptr<Segment> seg_ptr = nullptr;

    // 实际应用中，只需要修改这行代码就可以切换不同的算法，
	// 前后的代码都不需要修改，减少了代码的修改量。
    factory_ptr.reset(new CTFactory());

    pre_ptr.reset(factory_ptr->set_preprocessing());
    seg_ptr.reset(factory_ptr->set_segment());
    print_info(pre_ptr.get(), seg_ptr.get());

    cout << "\n\nchange new alg to segmentation...." << endl;
    factory_ptr.reset(new MRFactory());

    pre_ptr.reset(factory_ptr->set_preprocessing());
    seg_ptr.reset(factory_ptr->set_segment());
    print_info(pre_ptr.get(), seg_ptr.get());

	
	return 0;
}